/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SE_HIANALYTICS_H
#define SE_HIANALYTICS_H
#include <shared_mutex>
#include <string>

namespace OHOS {
namespace SE {

/** default log string */
static const std::string LOG_DEFAULT_STR = "";

/** base log index */
static const int LOG_BASE = 3000;

/** ServiceManager::OnStart() function called */
static const int LOG_ON_START = LOG_BASE + 1;

/** ServiceManager::Init() connected with hdf service + reader name list*/
static const int LOG_ON_BIND = LOG_BASE + 2;

/** ServiceManager::OnStop() function called */
static const int LOG_ON_STOP = LOG_BASE + 3;

/** Init Reader hdf fail +  reader name */
static const int LOG_ADD_TERMINAL_FAIL = LOG_BASE + 4;

/** openBasicChannel() function + aid + p2 */
static const int LOG_OPEN_BASIC_CHANNEL = LOG_BASE + 5;

/** openLogicalChannel() function + aid + p2 */
static const int LOG_OPEN_LOGICAL_CHANNEL = LOG_BASE + 6;

/** Init Reader hdf exception */
static const int LOG_GET_SERVICE_FAIL = LOG_BASE + 7;

/** OpenBasicChannel() fail + aid + p2 */
static const int LOG_OPEN_BASIC_CHANNEL_NULL = LOG_BASE + 8;

/** openLogicalChannel() fail + aid + p2 */
static const int LOG_OPEN_LOGICAL_CHANNEL_NULL = LOG_BASE + 9;

/** OpenBasicChannel() success + ChannelNumber */
static const int LOG_OPEN_BASIC_CHANNEL_SUCC = LOG_BASE + 10;

/** OpenLogicalChannel Success + ChannelNumber */
static const int LOG_OPEN_LOGICAL_CHANNEL_SUCC = LOG_BASE + 11;

/** ReaderImpl::GetAtr() return null */
static const int LOG_GET_ATR_NULL = LOG_BASE + 12;

/** no secure element present */
static const int LOG_SECURE_ELEMENT_NO_PRESENT = LOG_BASE + 13;

/** reader is not present while OpenSession() */
static const int LOG_READER_NULL = LOG_BASE + 14;

/** Session is closed */
static const int LOG_SESSION_IS_CLOSED = LOG_BASE + 15;

/** OpenBasicChannel() success  + select response */
static const int LOG_OPEN_BASIC_CHANNEL_RESP = LOG_BASE + 16;

/** basic channel in use */
static const int LOG_BASIC_CHANNEL_IN_USE = LOG_BASE + 17;

/** "default application is not selected"  Not implemented for now */
static const int LOG_DEF_APP_NO_SELECTED = LOG_BASE + 18;

/** Secure Element is not connected while open channel */
static const int LOG_SECURE_ELEMENT_NO_CONNECT = LOG_BASE + 19;

/** open Channel IOException */
static const int LOG_CHANNEL_IOEXCEPTION = LOG_BASE + 20;

/** OpenLogicChannel() success  + select response */
static const int LOG_OPEN_LOGICAL_CHANNEL_RESP = LOG_BASE + 21;

/** SecureElementAgent::OnStateChange() + state */
static const int LOG_SE_HAL_STATE = LOG_BASE + 22;

/** Below Maybe no need */
static const int LOG_OPEN_SE_NULL_BUNDLE = LOG_BASE + 23;

/** Below Maybe no need */
static const int LOG_OPEN_SE_INTERNAL_CONNECT_FAIL = LOG_BASE + 24;

/** Below Maybe no need */
static const int LOG_NO_NFC_ADAPTER = LOG_BASE + 25;

/** Below Maybe no need */
static const int LOG_NO_NFC_INTERFACE = LOG_BASE + 26;

/** Below Maybe no need */
static const int LOG_INTERNAL_OPEN_LOGICAL_CHANNEL_RESP = LOG_BASE + 27;

/** Below Maybe no need */
static const int LOG_INTERNAL_OPEN_LOGICAL_CHANNEL_SELECT = LOG_BASE + 28;

/** Below Maybe no need */
static const int LOG_OPEN_LOGICAL_CHANNEL_SELECT = LOG_BASE + 29;

/** Below Maybe no need */
static const int LOG_INTERNAL_CLOSE_LOGICAL_CHANNEL = LOG_BASE + 30;

/** Below Maybe no need */
static const int LOG_INTERNAL_CLOSE_LOGICAL_CHANNEL_RESP = LOG_BASE + 31;

/** ChannelImpl::Close() + channel number */
static const int LOG_CLOSE_LOGICAL_CHANNEL_FAIL = LOG_BASE + 32;

/** Below Maybe no need */
static const int LOG_NFC_ADAPTER_NULL = LOG_BASE + 33;

/** SecureElementAgent::Transmit() + SE name */
static const int LOG_TRANSMIT_NULL_BUNDLE = LOG_BASE + 34;

/** SecureElementAgent::Transmit() exception + SE name */
static const int LOG_TRANSMIT_EXCEPTION = LOG_BASE + 35;

/** SecureElementAgent::Transmit() response empty" */
static const int LOG_TRANSMIT_RESP_EMPTY = LOG_BASE + 36;

/** SecureElementAgent::Transmit() + cmd */
static const int LOG_TRANSMIT_CMD = LOG_BASE + 37;

/** SecureElementAgent::Transmit() + response */
static const int LOG_TRANSMIT_RSP = LOG_BASE + 38;

/** close unclose logic channelNum */
static const int LOG_CLOSE_UNCLOSE_CHANNEL = LOG_BASE + 39;

/** Below Maybe no need */
static const int LOG_OPEN_LOGICAL_CHANNEL_ALL = LOG_BASE + 40;

/** Below Maybe no need */
static const int LOG_OPEN_LOGICAL_CHANNEL_SUCC_ALL = LOG_BASE + 41;

/* 50K, The upper-layer service (HA) supports a maximum size of 128k,
** and the nfc service supports a maximum size of 8k each time, 8 + 50 < 128
**/
static const uint32_t FILE_MAX_SIZE = 1024 * 5 * 10;
static const uint16_t EVENT_LOG_MAX_SIZE = 1024;

constexpr const char* EVENT_TYPE_SE = "seEvent";
// nfc service will read the file and upload the content
constexpr const char* SE_EVENT_FILE_PATH = "/data/nfc/se_event.json";
constexpr const char* COMMA_PARSER = ", ";
constexpr const char* VERTICAL_BAR_PARSER = "|";

class SeHiAnalytics {
public:
    static SeHiAnalytics& GetInstance();
    void SeEventLog(int logId, const std::string &arg);
    void SeEventLog(int logId, const std::string &arg1, const std::string &arg2);
    // called while unload SA
    void WriteLogWithoutCondition();

private:
    SeHiAnalytics();
    ~SeHiAnalytics() {}
    uint32_t AppendSeEventLog(int logId, const std::string &arg);
    uint32_t AppendSeEventLog(int logId, const std::string &arg1, const std::string &arg2);
    void WriteLogToFile();
    void CheckAndRmvLogFile();

    /*  Event log structure:
        YYYY-MM-DD HH:MM:SS.NNN, logId, arg1, arg2| YYYY-MM-DD HH:MM:SS.NNN, logId, arg1, arg2| ... */
    std::string seEventLog_ = "";
    std::shared_mutex mutex_;
};

}
}
#endif